package hms.generic;

import hms.master.MasterController;
import hms.master.MasterView;

import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.WindowEvent;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

/**
 * <h2>Class Overview</h2> 
 * GUIBuilder that is used by the generic abstract View class to build the actual
 * window, etc. It assigns the MasterView as the event handler for the main screen
 * and also controlling opening of new views.
 * @author Matthew Johnson
 */

// TODO: Finish class overview comments

public class GUIViewBuilder extends JFrame {

	// This was added automatically by Eclipse
	private static final long serialVersionUID = 1L;
	
	// Create instances of menu components
	private JMenuBar menuBar;
	private JMenu menu_file;
	private JMenuItem menuItem_exit;
	private JMenuItem menuItem_login;
	
	// Panel to be passed in by other views
	private JPanel contentPanel;
	
	private JButton reservationModule;
	private JButton frontDeskModule;
	private JButton roomManagementModule;
	private JButton hotelAdminModule;
	private JButton userAccountModule;
	
	
	// Constraints for the layout
	private GridBagConstraints c;
	
	// Instance of the master view
	MasterView master;
	/**
	 * CONSTRUCTOR 
	 * TODO: Finish adding comments
	 */
	public GUIViewBuilder(JPanel i_contentPanel, MasterView i_master){
		
		// Assign the MasterView
		master = i_master;
		
		// Assign content panel associated with each unique view
		contentPanel = i_contentPanel;
		
		// Initialize GridBagConstraints
		c = new GridBagConstraints();
		c.fill = GridBagConstraints.BOTH;
		
		// Set the layout to a GridBag
		this.setLayout(new GridBagLayout());
				
		// Set the look and feel if available on computer
		setLookAndFeel();
		
		// Create the base outline of the standard view
		createWindowLayout();

	}
	
	/**
	 * This method sets the properties for the JFrame and calls methods which
	 * handle initializing all components and setting action listeners.
	 */
	public void createWindowLayout(){
		
		// TODO: Complete final layout tweaks and make it look better
		
		/*
		 * Initialize the Window's properties here, then call methods for
		 * creating and managing all other components
		 */
		
		// Set Menu for JFrame
		this.setJMenuBar(menuBar);
		
		// Set JFrame to maximized
		this.setExtendedState(Frame.MAXIMIZED_BOTH);
		
		// Default close operation
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

		// TODO ENABLE THIS IN FINAL PROGRAM
		// Set JFrame to full-screen
		this.setUndecorated(false);
		
		// TODO DISABLE THIS IN FINAL PROGRAM
		// Do not allow JFrame to be resizable
		this.setResizable(true);
		
		// Initialize Menu Bar Components
		initializeMenuBar();
		
		// Initialize Module Components
		initializeModules();
		
		// Initialize beginning content panel
		initializeContentPanel();
		
		// TODO: Possibly need to create a method to initialize a JPanel to store
		// the individual components from other views, but this might not be necessary.
		// Testing will have to be done to see how well this works.

		// Set the Action Commands and Event Listeners for the components
		setListeners();

	}
	
	/**
	 * Initialize the components associated with the JMenu which should always
	 * be displayed at the top of the screen everywhere except the splash screen.
	 */
	private void initializeMenuBar(){
		
		// Initialize Menu Bar
		menuBar = new JMenuBar();
		
		// Initialize Menus
		menu_file = new JMenu("File");
		menu_file.setToolTipText("File Menu");
		
		// Initialize Menu Items
		menuItem_exit = new JMenuItem("Exit");
		menuItem_login = new JMenuItem("Login");
		
		// Add Menus to Menu Bar
		menuBar.add(menu_file);
		
		// Add Menu Items to Menus
		menu_file.add(menuItem_login);
		menu_file.add(menuItem_exit);
		
		// Add Menu to JFrame
		this.setJMenuBar(menuBar);
		
		// TODO: Finish adding menu items.
		
	}
	
	/**
	 * Initialize the components associated with the modules which should always
	 * be displayed at the bottom of the screen everywhere except the splash screen.
	 */
	private void initializeModules(){
		
		// TODO: Add the module initialization here
		
		c.ipady = 50;

		reservationModule = new JButton("Reservations");
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.SOUTH;
		c.weightx = .5;
		c.gridx = 0;
		c.gridy = 1;
		this.add(reservationModule, c);
		
		frontDeskModule = new JButton("Front Desk");
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.SOUTH;
		c.weightx = .5;
		c.gridx = 1;
		c.gridy = 1;
		this.add(frontDeskModule, c);
		
		roomManagementModule = new JButton("Room Management");
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.SOUTH;
		c.weightx = .5;
		c.gridx = 2;
		c.gridy = 1;
		this.add(roomManagementModule, c);
		
		hotelAdminModule = new JButton("Hotel Administration");
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.SOUTH;
		c.weightx = .5;
		c.gridx = 3;
		c.gridy = 1;
		this.add(hotelAdminModule, c);
		
		userAccountModule = new JButton("User Accounts");
		c.fill = GridBagConstraints.BOTH;
		c.anchor = GridBagConstraints.SOUTH;
		c.weightx = .5;
		c.gridx = 4;
		c.gridy = 1;
		this.add(userAccountModule, c);
	
	}
	
	// TODO: Finish adding comments
	private void initializeContentPanel(){
		// Add the content panel to the main JFrame
				c.fill = GridBagConstraints.BOTH;
				c.gridx = 0;
				c.gridwidth = 5;
				c.weightx = 1;
				c.weighty = 1;
				c.gridy = 0;
		this.add(contentPanel, c);
	}
	
	/**
	 * Sets both the action commands (which should be the same as the variable
	 * name of the component) and the action listener (which should be this object)
	 * for all components that need them. Action commands are used by the action
	 * listener to identify which component initiated the call to the action listener.
	 */
	private void setListeners(){
		
		// Set Action Commands
		menuItem_exit.setActionCommand("menuItem_exit");
		menuItem_login.setActionCommand("menuItem_login");
		
		// Set Action Listeners
		menuItem_exit.addActionListener( master );
		menuItem_login.addActionListener( master );
		
		// Set Mouse Listeners for module buttons
		reservationModule.addMouseListener( master );
		frontDeskModule.addMouseListener( master );
		roomManagementModule.addMouseListener( master );
		hotelAdminModule.addMouseListener( master );
		userAccountModule.addMouseListener( master );
		
	}
	
	/**
	 * Makes the GUI visible. Should be called after everything is initialized
	 */
	public void display(){
		
		// Set this JFrame object to visible
		this.setVisible(true);
		
	}
	
	/**
	 * This should be called before creating a new view. It removes the panel from the currently
	 * displayed view so that the newly created view can pass in its own content panel to be displayed.
	 */
	public void destroy(){
		
		// Remove the current content panel from the JFrame
		this.remove(contentPanel);
		
	}
	
	/**
	 * Update the main view of the screen (not the menu or module buttons) to display a panel that
	 * is passed in from another view. Should be a complete panel already laid out. Be sure to call
	 * destroy() before creating the instance of a view that will use these methods initially.
	 * 
	 * For instance if ViewOne is replaced by ViewTwo, ViewOne should call super.destroy() before
	 * creating an instance of ViewTwo. ViewTwo should then create its panel and call super.update()
	 * and super.display()
	 * 
	 * @param i_contentPanel The panel to set within the main view
	 */
	public void update(JPanel i_contentPanel){
		
		// Set the local panel equal to the passed in parameter
		contentPanel = i_contentPanel;
		
		// Add the content panel to the main JFrame
		c.fill = GridBagConstraints.BOTH;
		c.gridx = 0;
		c.gridwidth = 5;
		c.weightx = 1;
		c.weighty = 1;
		c.gridy = 0;
		
		this.add(contentPanel, c);
	}
	
	/**
	 * Attempts to set the look and feel of the Java Swing package to the more
	 * updated Nimbus look. If not available, default look and feel is used.
	 */
	public void setLookAndFeel(){
		
		// This is a try-catch block to try and set the GUI to Nimbus, which is
		// a more updated and nicer looking GUI.
		try {
		    for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
		        if ("Nimbus".equals(info.getName())) {
		            UIManager.setLookAndFeel(info.getClassName());
		            break;
		        }
		    }
		} catch (Exception e) {
		    // If Nimbus is not available (JDK 6+ required), then the default
			// look and feel will be shown.
		}
	}
	
	/**
	 * Update the text of the login button. This should only be called when the global property
	 * isLoggedIn changes.
	 */
	public void updateLoginButton(){
		
		// If text says login, change to logout
		if(menuItem_login.getText().equalsIgnoreCase("Login"))
			menuItem_login.setText("Logout");
		
		// If text says logout, change to login
		else
			menuItem_login.setText("Login");
	}
	
	/**
	 * Access JButtons associated with the modules at the bottom of the screen
	 * 
	 * @return Array of JButtons for the modules in the order they appear on screen
	 */
	public JButton[] getModuleButtons(){
		
		// Create the array of all the buttons
		JButton[] arrayButtons = {reservationModule, frontDeskModule, roomManagementModule, hotelAdminModule, userAccountModule};
		
		// Return the array of buttons
		return arrayButtons;
	}
	
	/**
	 * This closes the database whenever the 'x' button in the top right corner of the window is clicked.
	 */
	@Override
	public void dispose(){
		
		// Call super method
		super.dispose();
		
		// Close database
		MasterController.closeDatabaseConnection();
	}

}
